package org.ytor.common.util.excel;

import lombok.Data;
import lombok.NonNull;
import lombok.experimental.Accessors;
import org.ytor.common.classmeta.ClassMetadata;
import org.ytor.common.enums.ExcelVersion;
import org.ytor.common.util.cache.ClassCache;
import org.ytor.common.util.excel.support.DefaultExcelFieldHandlerFactory;

import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * created by yangtong on 2025/5/29 20:46:47
 * <br/>
 * Excel读取或写入时的一些配置
 */
@Data
@Accessors(chain = true)
public class ExcelConfig<T> {
    /**
     * 读取exel第几个sheet的内容，默认第一个（下标0）
     */
    private Integer sheet = 0;

    /**
     * 表头所在行
     */
    private Integer headerRowIndex = 0;

    /**
     * 从第几行开始读取
     */
    private Integer startRow = 0;

    /**
     * 从第几列开始读取
     */
    private Integer startCol = 0;

    /**
     * 将excel读取成指定类型
     */
    private Class<T> targetClazz;

    /**
     * 类元信息
     */
    private ClassMetadata<T> classMetadata;

    /**
     * 目标对象中加了Excel注解的字段信息
     */
    private List<ExcelAnnoHandler> annoFields;

    /**
     * 表头和Excel注解的对照关系
     */
    private Map<String, ExcelAnnoHandler> annoHeaderFieldMapper;

    /**
     * 是否启用列名匹配模式
     */
    private Boolean headerMappingEnabled = true;

    /**
     * 默认操作的07版本的xlsx
     */
    private ExcelVersion version = ExcelVersion.V07;

    /**
     * 将excel数据写到指定输出流
     */
    private OutputStream out;

    /**
     * 是否在导出的excel里面显示导出信息
     */
    private Boolean showExpertInfo = true;

    public ExcelConfig(@NonNull Class<T> targetClazz) {
        this(targetClazz, DefaultExcelFieldHandlerFactory.getInstance());
    }

    public ExcelConfig(@NonNull Class<T> targetClazz, @NonNull ExcelFieldHandlerFactory factory) {
        this.targetClazz = targetClazz;
        this.classMetadata = ClassCache.get(targetClazz);

        //获取目标对象中标准了Excel注解的字段
        annoFields = classMetadata.getFields().stream()
                .map(field -> new ExcelAnnoHandler(field, factory))
                .filter(ExcelAnnoHandler::hasExcel)
                .toList();
        //解析表头和Excel注解的对照关系
        annoHeaderFieldMapper = annoFields.stream()
                .filter(h -> !h.getExcel().value().trim().isBlank())
                .collect(Collectors.toMap(h -> h.getExcel().value().trim().toLowerCase(), Function.identity()));
    }

    /**
     * 从指定模板加载
     */
    public ExcelConfig<T> form(InputStream in) {
        return this;
    }

    /**
     * 将excel写入到指定输出流
     */
    public ExcelConfig<T> to(OutputStream out) {
        if (!(out instanceof BufferedOutputStream)) {
            out = new BufferedOutputStream(out);
        }
        this.out = out;
        return this;
    }

}
